<template>
	
	<!-- 允许冒泡 -->
	<view v-if="bubble==true || bubble=='true'"
	class="_focus-box-shell-class" :class="classBox" :style="styleBox" bubble="true"
	:elevation="(shadow==true||shadow=='true')&&state.isNvue&&state.isAndroid ? '8px' : 'none'"
	@tap="onBoxClick" @longpress="onBoxLongClick">
		<slot></slot>
	</view>
	
	<!-- 默认情况：阻止冒泡 -->
	<view v-else
	class="_focus-box-shell-class" :class="classBox" :style="styleBox"
	:elevation="(shadow==true||shadow=='true')&&state.isNvue&&state.isAndroid ? '8px' : 'none'"
	@tap.stop="onBoxClick" @longpress.stop="onBoxLongClick">
		<slot></slot>
	</view>
	
</template>


<script>
	/**
	 * 布局容器
	 * @description vue/nvue通用，基础类组件，弹性盒子容器，已经预设样式：box-sizing:border-box;
	 * @tutorial
	 * @property {String} tag 组件自定义标识，默认：focus-box
	 * @property {String,Number} width 容器宽度(rpx)
	 * @property {String,Number} height 容器高度(rpx)
	 * @property {String,Number,Array} padding 容器内边距(rpx)，数组形式，写法：[24]/[12,24]/[12,0,12,24]
	 * @property {String,Number,Array} margin 容器外边距(rpx)，数组形式，写法：[24]/[12,24]/[12,0,12,24]
	 * @property {String,Number,Array} radius 边框圆角(rpx)，数组形式，写法：[10]/[8,10]/[8,10,12,24]
	 * 
	 * @property {String} mode = [row|col|wrap] 容器主轴模式，默认：col
	 *   @value row 行布局容器
	 *   @value col 列布局容器
	 *   @value wrap 自动换行布局容器
	 * @property {String} justify = [start|center|end|around|between] 主轴线的对齐方式，默认：start
	 *   @value start 子级从主轴开始位置排列
	 *   @value center 子级从主轴居中位置排列
	 *   @value end 子级从主轴结束位置排列
	 *   @value around 子级按主轴平均分布
	 *   @value between 子级触及主轴首尾再平均分布
	 * @property {String} align = [start|center|end|stretch] 侧轴线的对齐方式，默认：center
	 *   @value start 子级从侧轴开始位置排列
	 *   @value center 子级从侧轴居中位置排列
	 *   @value end 子级从侧轴结束位置排列
	 *   @value stretch 子级直接拉伸为侧轴的100%
	 * @property {String,Number} flex = [1|2|3|4|5|6] 自身作为子级的占位比例
	 * 
	 * @property {String} bg = [black|white|primary|success|warning|error|info] 内置的背景颜色值域有代码提示；也可以直接填入十六进制RGB值，如：#FFFFFF
	 *   @value black 黑色
	 *   @value white 白色
	 *   @value primary 基本主体色
	 *   @value success 完成色
	 *   @value warning 警告色
	 *   @value error 错误色
	 *   @value info 信息色
	 * @property {String} bgscheme = [light|dark|disabled|gradual|hover] 背景颜色系别，仅支持内置bg值域，不填则使用常规
	 *   @value light 浅色系
	 *   @value dark 暗色系
	 *   @value disabled 禁用系
	 *   @value gradual 渐变系(仅primary/success/warning/error四种内置背景色有效)
	 *   @value hover 点击态
	 * 
	 * @property {String} border = [black|white|primary|success|warning|error|info] 内置的边框颜色值域有代码提示；也可以直接填入十六进制RGB值，如：#FFFFFF
	 *   @value black 黑色
	 *   @value white 白色
	 *   @value primary 基本主体色
	 *   @value success 完成色
	 *   @value warning 警告色
	 *   @value error 错误色
	 *   @value info 信息色
	 * @property {String} borderscheme = [light|dark|disabled|hover] 边框颜色系别，仅支持内置border值域，不填则使用常规
	 *   @value light 浅色系
	 *   @value dark 暗色系
	 *   @value disabled 禁用系
	 *   @value hover 点击态
	 * 
	 * @property {String} position = [relative|absolute|fixed|sticky] 容器定位方式
	 *   @value relative 相对定位
	 *   @value absolute 绝对定位(以元素的容器作为参考系)
	 *   @value fixed 悬浮定位(以页面窗口作为参考系)
	 *   @value sticky 当元素滚动到页面之外时生效定位
	 * @property {String,Number} top 距离上方的偏移量(rpx)
	 * @property {String,Number} bottom 距离下方的偏移量(rpx)
	 * @property {String,Number} left 距离左方的偏移量(rpx)
	 * @property {String,Number} right 距离右方的偏移量(rpx)
	 * @property {String} index = [1x|2x|3x|4x|5x] 容器定位层级优先级，默认：1x
	 *   @value 1x 推荐用于绝对定位类容器，相当于20
	 *   @value 2x 推荐用于绝对定位类容器，相当于40
	 *   @value 3x 推荐用于固定悬浮类容器，相当于60
	 *   @value 4x 推荐用于弹出类容器，相当于80
	 *   @value 5x 一定要显示，相当于100
	 * 
	 * @property {String,Boolean} shadow = [false|true] 是否开启底部阴影效果，默认：false
	 *   @value false 关闭底部阴影
	 *   @value true 开启底部阴影
	 * @property {String,Boolean} bubble = [false|true] 是否开启冒泡，默认：true
	 *   @value false 关闭冒泡功能
	 *   @value true 开启冒泡功能
	 * @property {Object} styles 组件自定义样式，必须使用object格式
	 * @event {Function} click 点击事件
	 * @event {Function} longclick 长按事件
	 */
	export default {
		name: "focus-box",
		// 传递数据
		props: {
			"tag": { type: String, default: 'focus-box' },
			"width": { type: [String,Number], default: null },
			"height": { type: [String,Number], default: null },
			"padding": { type: [String,Number,Array], default: null },
			"margin": { type: [String,Number,Array], default: null },
			"radius": { type: [String,Number,Array], default: null },
			
			"mode": { type: String, default: 'col' },
			"justify": { type: String, default: 'start' },
			"align": { type: String, default: 'center' },
			"flex": { type: [String,Number], default: null },
			
			"bg": { type: String, default: '' },
			"bgscheme": { type: String, default: '' },
			"border": { type: String, default: '' },
			"borderscheme": { type: String, default: '' },
			
			"position": { type: String, default: '' },
			"top": { type: [String,Number], default: null },
			"bottom": { type: [String,Number], default: null },
			"left": { type: [String,Number], default: null },
			"right": { type: [String,Number], default: null },
			"index": { type: String, default: '' },
			
			"shadow": { type: [String,Boolean], default: false },
			"bubble": { type: [String,Boolean], default: true },
			"styles": { type: Object, default: function() { return {}; } }
		},
		
		// 页面数据
		data() {
			return {
				
				// vue doc 格式规范：
				// * 这里是一个组件描述，会在提示标签的时候显示  
				// * @description 这里也是一个组件描述  
				// * @tutorial https://uniapp.dcloud.io/api/media/image?id=chooseimage  
				// * @property {String} type = [button|input|...值域] 这里是属性描述  
				// * @event {Function} tap 这是是事件描述   
				// * @example 这里是示例代码 
				
				// 状态信息
				state: {
					isAndroid: false, // 是否是安卓平台
					isNvue: false, // 是否是weex编译文件
				},
				
				// ------------------------------------ 时间记录
				// 手指按下时间戳
				time_start: 0
				
			}
		},
		
		// 组件创建完成
		created() {
			// 获取平台信息
			uni.getSystemInfo({
				success: (sysD) => {
					// 判断是否为安卓平台
					this.state.isAndroid = sysD.platform=='ios' ? false : true;
				}
			});
			// #ifdef APP-PLUS-NVUE
			this.state.isNvue = true;
			// #endif
		},
		
		// 计算属性
		computed: {
			// 容器class属性
			classBox() {
				// 初始化
				var arr_class = [];
				var str_class = '';
				
				// 使用内置背景颜色
				if (this.bg.length>0 && this.bg.indexOf('#')<0 && this.bg.indexOf('rgba')<0)
				{
					// 背景颜色 名称组合
					var className_bg = '_focus-bgColor-' + this.bg;
					// 是否传递背景色系
					if (this.bgscheme.length > 0) { className_bg += '-' + this.bgscheme; }
					// 类名添加
					arr_class.push(className_bg);
				}
				
				// 内置边框颜色
				if (this.border.length>0 && this.border.indexOf('#')<0 && this.border.indexOf('rgba')<0)
				{
					// 背景颜色 名称组合
					var className_border = '_focus-borderColor-' + this.border;
					// 是否传递背景色系
					if (this.borderscheme.length > 0) { className_border += '-' + this.borderscheme; }
					// 类名添加
					arr_class.push(className_border);
				}
				
				// 底部阴影效果
				if (this.shadow == true || this.shadow == 'true')
				{
					// 非nvue模式 || ios平台执行
					if (this.state.isNvue == false || this.state.isAndroid == false)
					{
						// 使用css来进行阴影设置
						arr_class.push('_focus-box-shadow-class');
					}
				}
				
				// 循环样式对象
				for (let k in arr_class) { str_class += arr_class[k] + ' '; }
				// 结果返回
				return str_class;
			},
			// 容器style属性
			styleBox() {
				// 初始化
				var obj_style = {};
				var str_style = '';
				
				
				// ======================================= 容器宽高
				if (this.width != null && Number(this.width) >= 0) { obj_style['width'] = this.width + 'rpx'; }
				if (this.height != null && Number(this.height) >= 0) { obj_style['height'] = this.height + 'rpx'; }
				
				// ======================================= 容器内边距
				// 传入的是 string 和 number 的情况
				if ( (typeof(this.padding)=="string" || typeof(this.padding)=="number") && this.padding)
				{
					obj_style['padding'] = this.padding + 'rpx';
				}
				// 传入的是 array 的情况
				else if (typeof(this.padding)=="object" && this.padding && this.padding.length)
				{
					// 只有一个元素
					if (this.padding.length == 1)
					{
						obj_style['padding'] = this.padding[0] + 'rpx';
					}
					// 有2个元素
					else if (this.padding.length == 2)
					{
						obj_style['padding-top'] = this.padding[0] + 'rpx';
						obj_style['padding-right'] = this.padding[1] + 'rpx';
						obj_style['padding-bottom'] = this.padding[0] + 'rpx';
						obj_style['padding-left'] = this.padding[1] + 'rpx';
					}
					// 有4个元素及以上
					else if (this.padding.length >= 4)
					{
						obj_style['padding-top'] = this.padding[0] + 'rpx';
						obj_style['padding-right'] = this.padding[1] + 'rpx';
						obj_style['padding-bottom'] = this.padding[2] + 'rpx';
						obj_style['padding-left'] = this.padding[3] + 'rpx';
					}
				}
				
				// ======================================= 容器外边距
				// 传入的是 string 和 number 的情况
				if ( (typeof(this.margin)=="string" || typeof(this.margin)=="number") && this.margin)
				{
					obj_style['margin'] = this.margin + 'rpx';
				}
				// 传入的是 array 的情况
				else if (typeof(this.margin)=="object" && this.margin && this.margin.length)
				{
					// 只有一个元素
					if (this.margin.length == 1)
					{
						obj_style['margin'] = this.margin[0] + 'rpx';
					}
					// 有2个元素
					else if (this.margin.length == 2)
					{
						obj_style['margin-top'] = this.margin[0] + 'rpx';
						obj_style['margin-right'] = this.margin[1] + 'rpx';
						obj_style['margin-bottom'] = this.margin[0] + 'rpx';
						obj_style['margin-left'] = this.margin[1] + 'rpx';
					}
					// 有4个元素及以上
					else if (this.margin.length >= 4)
					{
						obj_style['margin-top'] = this.margin[0] + 'rpx';
						obj_style['margin-right'] = this.margin[1] + 'rpx';
						obj_style['margin-bottom'] = this.margin[2] + 'rpx';
						obj_style['margin-left'] = this.margin[3] + 'rpx';
					}
				}
				
				// ======================================= 边框圆角
				// 传入的是 string 和 number 的情况
				if ( (typeof(this.radius)=="string" || typeof(this.radius)=="number") && this.radius)
				{
					obj_style['border-radius'] = this.radius + 'rpx';
				}
				// 传入的是 array 的情况
				else if (typeof(this.radius)=="object" && this.radius && this.radius.length)
				{
					// 只有一个元素
					if (this.radius.length == 1)
					{
						obj_style['border-radius'] = this.radius[0] + 'rpx';
					}
					// 有2个元素
					else if (this.radius.length == 2)
					{
						obj_style['border-top-left-radius'] = this.radius[0] + 'rpx';
						obj_style['border-top-right-radius'] = this.radius[1] + 'rpx';
						obj_style['border-bottom-right-radius'] = this.radius[0] + 'rpx';
						obj_style['border-bottom-left-radius'] = this.radius[1] + 'rpx';
					}
					// 有4个元素及以上
					else if (this.radius.length >= 4)
					{
						obj_style['border-top-left-radius'] = this.radius[0] + 'rpx';
						obj_style['border-top-right-radius'] = this.radius[1] + 'rpx';
						obj_style['border-bottom-right-radius'] = this.radius[2] + 'rpx';
						obj_style['border-bottom-left-radius'] = this.radius[3] + 'rpx';
					}
				}
				
				
				
				// ======================================= 容器主轴模式
				if (this.mode == 'col') { obj_style['flex-direction'] = 'column'; }
				else if (this.mode == 'wrap') { obj_style['flex-direction'] = 'row'; obj_style['flex-wrap'] = 'wrap'; }
				else { obj_style['flex-direction'] = 'row'; }
				
				// ======================================= 主轴线的对齐方式
				if (this.justify == 'center') { obj_style['justify-content'] = 'center'; }
				else if (this.justify == 'end') { obj_style['justify-content'] = 'flex-end'; }
				else if (this.justify == 'around') { obj_style['justify-content'] = 'space-around'; }
				else if (this.justify == 'between') { obj_style['justify-content'] = 'space-between'; }
				else { obj_style['justify-content'] = 'flex-start'; }
				
				// ======================================= 侧轴线的对齐方式
				if (this.align == 'start') { obj_style['align-items'] = 'flex-start'; }
				else if (this.align == 'end') { obj_style['align-items'] = 'flex-end'; }
				else if (this.align == 'stretch') { obj_style['align-items'] = 'stretch'; }
				else { obj_style['align-items'] = 'center'; }
				
				// ======================================= 自身作为子级的占位比例
				if (this.flex != null && Number(this.flex) >= 1) { obj_style['flex'] = this.flex; }
				
				
				
				// ======================================= 背景颜色(16进制)
				if (this.bg && (this.bg.indexOf('#')>=0 || this.bg.indexOf('rgba')>=0))
				{
					obj_style['background-color'] = this.bg;
				}
				
				// ======================================= 边框线条
				if (this.border.length > 0)
				{
					obj_style['border-width'] = '1px';
					obj_style['border-style'] = 'solid';
					// ======================================= 边框颜色(16进制)
					if (this.border.indexOf('#')>=0 || this.border.indexOf('rgba')>=0)
					{
						obj_style['border-color'] = this.border;
					}
				}
				
				
				
				// ======================================= 容器定位方式
				if (this.position.length > 0)
				{
					// 定位类型赋值
					obj_style['position'] = this.position;
					
					// ======================================= 定位的偏移量
					if (this.top != null && Number(this.top) >= 0) { obj_style['top'] = this.top + 'rpx'; }
					if (this.bottom != null && Number(this.bottom) >= 0) { obj_style['bottom'] = this.bottom + 'rpx'; }
					if (this.left != null && Number(this.left) >= 0) { obj_style['left'] = this.left + 'rpx'; }
					if (this.right != null && Number(this.right) >= 0) { obj_style['right'] = this.right + 'rpx'; }
					
					// ======================================= 容器定位层级优先级
					if (this.index == '2x') { obj_style['z-index'] = 40; }
					else if (this.index == '3x') { obj_style['z-index'] = 60; }
					else if (this.index == '4x') { obj_style['z-index'] = 80; }
					else if (this.index == '5x') { obj_style['z-index'] = 100; }
					else { obj_style['z-index'] = 20; }
				}
				
				
				// ======================================= 用户自定义
				if (typeof(this.styles)=="object") { obj_style = Object.assign(obj_style, this.styles); }
				
				// 循环样式对象
				for (let k in obj_style) { str_style += k + ':' + obj_style[k] + ';'; }
				// 结果返回
				return str_style;
			}
		},
		
		// 组件事件
		methods: {
			
			// 容器点击
			onBoxClick(ev) {
				// 记录按下时候的时间戳
				var timestamp_start = new Date().getTime();
				// 防止连续重复触发
				if (timestamp_start - this.time_start > 1000)
				{
					// 时间戳覆盖赋值
					this.time_start = timestamp_start;
					// 点击事件传递给父级
					this.$emit('click', { "tag": this.tag });
				}
				// nvue条件渲染
				// #ifdef APP-NVUE
				// 如果关闭事件冒泡
				if (this.bubble==false || this.bubble=='false') { ev.stopPropagation(); }
				// #endif
			},
			
			// 容器长按
			onBoxLongClick(ev) {
				// 长按事件传递给父级
				this.$emit('longclick', { "tag": this.tag });
				// nvue条件渲染
				// #ifdef APP-NVUE
				// 如果关闭事件冒泡
				if (this.bubble==false || this.bubble=='false') { ev.stopPropagation(); }
				// #endif
			}
			
		}
		
	}
</script>


<style lang="scss">
	// 背景颜色文件
	@import "../../lib/css/style-background.scss";
	// 边框颜色文件
	@import "../../lib/css/style-border.scss";
	
	/* 弹性盒子布局 */
	._focus-box-shell-class{
		/* #ifndef APP-NVUE */
		display: flex; box-sizing: border-box;
		/* #endif */
	}
	
	/* IOS使用的阴影样式 */
	._focus-box-shadow-class{
		/* #ifndef APP-NVUE */
		box-shadow: 0px 3px 16px #A7A7A7;
		/* position: relative; */
		/* #endif */
		/* #ifdef APP-NVUE */
		box-shadow: 0px 3px 8px #A7A7A7;
		/* #endif */
	}
	/* 根据容器自身背景颜色形成对应色底部阴影 - 兼容性差，待定
	._focus-box-shadow-class::before{
		content: "";
		width: 100%; height: 100%;
		position: absolute; top: 10rpx; left: 10rpx; z-index: -1;
		display: block; border-radius: inherit;
		background-color: inherit;
		filter: blur(10rpx); opacity: 0.4;
		transform-origin: 0 0; transform: scale(1, 1);
	}
	*/
</style>